summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/time/clock_types.h
blob: e6293ffb9b9fba627904ce9c0408fe7d2853dfd6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/uuid.h"
#include "core/hle/service/time/errors.h"
#include "core/hle/service/time/time_zone_types.h"

namespace Service::Time::Clock {

enum class TimeType : u8 {
    UserSystemClock,
    NetworkSystemClock,
    LocalSystemClock,
};

/// https://switchbrew.org/wiki/Glue_services#SteadyClockTimePoint
struct SteadyClockTimePoint {
    s64 time_point;
    Common::UUID clock_source_id;

    Result GetSpanBetween(SteadyClockTimePoint other, s64& span) const {
        span = 0;

        if (clock_source_id != other.clock_source_id) {
            return ERROR_TIME_MISMATCH;
        }

        span = other.time_point - time_point;

        return ResultSuccess;
    }

    static SteadyClockTimePoint GetRandom() {
        return {0, Common::UUID::MakeRandom()};
    }
};
static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size");
static_assert(std::is_trivially_copyable_v<SteadyClockTimePoint>,
              "SteadyClockTimePoint must be trivially copyable");

struct SteadyClockContext {
    u64 internal_offset;
    Common::UUID steady_time_point;
};
static_assert(sizeof(SteadyClockContext) == 0x18, "SteadyClockContext is incorrect size");
static_assert(std::is_trivially_copyable_v<SteadyClockContext>,
              "SteadyClockContext must be trivially copyable");
using StandardSteadyClockTimePointType = SteadyClockContext;

struct SystemClockContext {
    s64 offset;
    SteadyClockTimePoint steady_time_point;
};
static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext is incorrect size");
static_assert(std::is_trivially_copyable_v<SystemClockContext>,
              "SystemClockContext must be trivially copyable");

struct ContinuousAdjustmentTimePoint {
    s64 measurement_offset;
    s64 diff_scale;
    u32 shift_amount;
    s64 lower;
    s64 upper;
    Common::UUID clock_source_id;
};
static_assert(sizeof(ContinuousAdjustmentTimePoint) == 0x38);
static_assert(std::is_trivially_copyable_v<ContinuousAdjustmentTimePoint>,
              "ContinuousAdjustmentTimePoint must be trivially copyable");

/// https://switchbrew.org/wiki/Glue_services#TimeSpanType
struct TimeSpanType {
    s64 nanoseconds{};
    static constexpr s64 ns_per_second{1000000000ULL};

    s64 ToSeconds() const {
        return nanoseconds / ns_per_second;
    }

    static TimeSpanType FromSeconds(s64 seconds) {
        return {seconds * ns_per_second};
    }

    static TimeSpanType FromTicks(u64 ticks, u64 frequency) {
        return FromSeconds(static_cast<s64>(ticks) / static_cast<s64>(frequency));
    }
};
static_assert(sizeof(TimeSpanType) == 8, "TimeSpanType is incorrect size");

struct ClockSnapshot {
    SystemClockContext user_context;
    SystemClockContext network_context;
    s64 user_time;
    s64 network_time;
    TimeZone::CalendarTime user_calendar_time;
    TimeZone::CalendarTime network_calendar_time;
    TimeZone::CalendarAdditionalInfo user_calendar_additional_time;
    TimeZone::CalendarAdditionalInfo network_calendar_additional_time;
    SteadyClockTimePoint steady_clock_time_point;
    TimeZone::LocationName location_name;
    u8 is_automatic_correction_enabled;
    TimeType type;
    INSERT_PADDING_BYTES_NOINIT(0x2);

    static Result GetCurrentTime(s64& current_time,
                                 const SteadyClockTimePoint& steady_clock_time_point,
                                 const SystemClockContext& context) {
        if (steady_clock_time_point.clock_source_id != context.steady_time_point.clock_source_id) {
            current_time = 0;
            return ERROR_TIME_MISMATCH;
        }
        current_time = steady_clock_time_point.time_point + context.offset;
        return ResultSuccess;
    }
};
static_assert(sizeof(ClockSnapshot) == 0xD0, "ClockSnapshot is incorrect size");

} // namespace Service::Time::Clock